package SelectRole

import (
	codecs "sanguo/codec/cs"
	"sanguo/node/common/asynwrap"
	"sanguo/node/common/db"
	"sanguo/node/common/transaction"
	"sanguo/node/node_game"
	"sanguo/node/node_game/module/role"
	"sanguo/node/node_game/user"
	cs_message "sanguo/protocol/cs/message"
	"strconv"
	"time"

	"github.com/go-redis/redis"
	"github.com/golang/protobuf/proto"
)

type transactionSelectRole struct {
	transaction.TransactionBase
	user    *user.User
	req     *codecs.Message
	resp    *cs_message.SelectRoleToC
	errcode cs_message.EnumType
}

func (this *transactionSelectRole) GetModuleName() string {
	return "SelectRole"
}

func (this *transactionSelectRole) GetReplyMsg() proto.Message {
	return &cs_message.SelectRoleToC{}
}

func (this *transactionSelectRole) SetExpiredTime(expired time.Time) {
	this.Expired = expired
}

func (this *transactionSelectRole) GetExpiredTime() time.Time {
	return this.Expired
}

func (this *transactionSelectRole) Begin() {

	msg := this.req.GetData().(*cs_message.SelectRoleToS)
	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
	node_game.Infoln(this.user.GetUserID(), " selectRole :", msg.GetID())
	currentRole := roleModule.CurrentRole()
	r := roleModule.GetRole(msg.GetID())

	//待修改
	if currentRole != nil {
		node_game.Infoln(this.user.GetUserID(), "currentRole != nil ")
		roleModule.ClearInstanceZone()

		if currentRole.NodeMap != nil {
			roleModule.ClearMap()
		}
	}

	if r == currentRole {
		this.PackAllRoleData(r)
		this.errcode = cs_message.EnumType_OK
		this.user.EndTrans(this)
		return
	}

	if r != nil {
		r.SetSelectRoleOk(false)
		if r.IsRoleModleData() {

			this.SelectRole(r)
		} else {
			//加载RoleModleData
			node_game.Infoln(msg.GetID(), "RoleModleData nil ")
			this.LoadRoleAllData(r)
		}

	} else {
		node_game.Infoln(this.user.GetUserID(), " Role nil ")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
	}
}
func (this *transactionSelectRole) LoadRoleAllData(r *role.Role) {
	key := "roleModuleData:" + strconv.FormatUint(r.GetID(), 10)
	asynwrap.Wrap(db.GetRedisClient("game").HGetAll)(func(ret []interface{}) {
		if !this.user.CheckTrans(this) {
			return
		}
		result, err := ret[0].(*redis.StringStringMapCmd).Result()
		if nil != err {
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}

		//初始化rolemoduledata
		if r.InitRoleAllModuleData(result) {
			node_game.Infoln(r.GetUserID(), r.GetID(), "InitRoleAllModuleData ok ")
			this.SelectRole(r)
		} else {
			node_game.Infoln(r.GetUserID(), r.GetID(), "InitRoleAllModuleData fail ")
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
		}
	}, key)
}

func (this *transactionSelectRole) SelectRole(r *role.Role) {
	msg := this.req.GetData().(*cs_message.SelectRoleToS)
	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)

	roleModule.OnSelectRole(r)
	roleModule.SelectRole(msg.GetID())

	roleModule.ChangeRoleUsed(msg.GetID()) //改变后需要存库的roleID
	this.PackAllRoleData(r)

	/*
		v1, err := r.ToJsonStr() //json.Marshal(r)
		if nil != err {
			this.errcode = cs_message.EnumType_ERROR
			this.user.EndTrans(this)
			return
		}

		key := "role:" + this.user.GetUserID()
		asynwrap.Wrap(db.GetRedisClient("game").HSet)(func(ret []interface{}) {
			_, err := ret[0].(*redis.BoolCmd).Result()
			if nil != err {
				this.errcode = cs_message.EnumType_ERROR
				this.user.EndTrans(this)
				return
			} else {
				this.errcode = cs_message.EnumType_OK
				this.PackAllRoleData(r)
			}
		}, key, strconv.FormatUint(msg.GetID(), 10), v1)

		if len(otherRoleIds) != 0 {
			for _, roleID := range otherRoleIds {
				changedRole := roleModule.GetRole(roleID)
				v2, err := changedRole.ToJsonStr() //json.Marshal(changedRole)
				if nil != err {
					this.errcode = cs_message.EnumType_ERROR
					this.user.EndTrans(this)
					return
				}

				key := "role:" + this.user.GetUserID()
				asynwrap.Wrap(db.GetRedisClient("game").HSet)(func(ret []interface{}) {
					_, err := ret[0].(*redis.BoolCmd).Result()
					if nil != err {
						this.errcode = cs_message.EnumType_ERROR
						this.user.EndTrans(this)
						return
					} else {
						this.errcode = cs_message.EnumType_OK
					}
				}, key, strconv.FormatUint(roleID, 10), v2)
			}
		}*/
}

func (this *transactionSelectRole) PackAllRoleData(r *role.Role) {
	//	选角成功 向客户端发送所有数据
	this.resp = &cs_message.SelectRoleToC{
		ID:           proto.Uint64(r.GetID()),
		Missions:     r.GetRoleMission().PackAllMission(),
		Attrs:        r.GetRoleAttr().PackAllAttr(),
		BattleAttrs:  r.GetRoleBattleAttr().PackAllBattleAttr(),
		Items:        r.GetRoleItem().PackAllItem(),
		Weapons:      r.GetRoleWeapon().PackAllWeapon(),
		WeaponShards: r.GetRoleWeaponShard().PackAllWeaponShard(),
		RoleSkills:   r.GetRoleSkill().PackSkill(),
		Souls:        r.GetRoleSoul().PackAllSoul(),
		StarMap:      r.GetRoleStarMap().PackAllStarMap(),
		DrawCards:    r.GetRoleDrawCard().PackAllDrawCard(),
		BossZones:    r.GetRoleBossZone().PackAllBossZone(),
	}

	//node_game.Infoln("selectRole roleData", this.resp)
	this.errcode = cs_message.EnumType_OK
	this.user.EndTrans(this)
}

func (this *transactionSelectRole) End() {
	if this.errcode == cs_message.EnumType_OK {

		this.resp.Errcode = cs_message.EnumType(this.errcode).Enum()

		//选角成功
		roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
		role := roleModule.CurrentRole()
		role.SetSelectRoleOk(true)
		roleModule.OnLine()
		node_game.Infoln(this.user.GetUserID(), " selectRole ok", role.GetID())
	} else {
		node_game.Infoln(this.user.GetUserID(), " selectRole fail")
		this.resp = &cs_message.SelectRoleToC{
			Errcode: cs_message.EnumType(this.errcode).Enum(),
		}
	}
	this.user.Reply(this.req.GetSeriNo(), this.resp)

}

func (this *transactionSelectRole) Timeout() {
	this.errcode = cs_message.EnumType_RETRY
	this.user.EndTrans(this)
}

func init() {
	user.RegisterTransFunc(&cs_message.SelectRoleToS{}, func(user *user.User, msg *codecs.Message) transaction.Transaction {
		return &transactionSelectRole{
			user: user,
			req:  msg,
		}
	})
}
